package com.ym.b2b.payment.controller.fmcib;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ym.b2b.commons.conf.B2BConstants;
import com.ym.b2b.commons.conf.WebTokenUser;
import com.ym.b2b.commons.controller.BaseController;
import com.ym.b2b.commons.util.Md5encode;
import com.ym.b2b.order.dao.EmSOrderDao;
import com.ym.b2b.order.sqlbean.EmSOrder;
import com.ym.b2b.payment.service.EmSPaymentService;
import com.ym.b2b.payment.sqlbean.EmSPayment;
import com.ym.b2b.user.dao.EmCUserDAO;
import com.ym.b2b.user.sqlbean.EmCUser;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.util.HttpURLConnection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * Created by Administrator on 2015/7/20.
 */

@Controller
@RequestMapping("/fmcib")
public class FmcibController  extends BaseController {
    private final String ORDER_SAVE_URL="http://pay.fmcib.com.cn/anon/ofp/thdOrder/orderSave.json";   //订单导入地址
    private final String PAY_SELECT_URL="http://pay.fmcib.com.cn/anon/pay/payment/getPaySelect.do";   //订单支付地址
    private final String TK_CUST_ID="Tjntkyywl";     //宣城客户编号
    private final String TK_RECEIVABLE_NO="376120100100088678"; // TODO 宣城应收账款号
    private final String TK_KEY="b655fa50ec161e3e46cff1a623a61515"; //宣城通信密钥
    private final String ORDER_TITLE="宣城医药商品";

    @Autowired
    private EmSOrderDao emSOrderDao;

    @Autowired
    private EmCUserDAO emCUserDAO;

    @Autowired
    private EmSPaymentService emSPaymentService;

    /**
     * 随兴盈支付
     */
    @RequestMapping("getInfoForFee.s")
    public ModelAndView getInfoForFee(EmSOrder emSOrder, HttpServletRequest req) {
        ModelAndView m = new ModelAndView();
        try{
            WebTokenUser token = getWebTokenUser(req);
            if (null == token) {
                m.setViewName(B2BConstants.WEB_NOT_LOGIN);
                return m;
            }
            // 组装需要塞入的订单信息
            EmSOrder order = emSOrderDao.searchOrderDetail(emSOrder);
            if (null == order || order.getStatus() >= 20) {
                m.addObject("info", "订单已经支付过了  不能重复提交!");
                m.setViewName(B2BConstants.WEB_ERROR);
                return m;
            }
            EmCUser emCUser = new EmCUser();
            emCUser.setUserId(token.getUserId());
            emCUser = emCUserDAO.searchEmCUser(emCUser);

            //兴业要求订单时间为当前时间
            order.setUpdateDate(new Date());

            OrderInFmcibParam orderInFmcibParam=this.putOrderInParam(order,emCUser);
            boolean flag=this.doPostStatus(orderInFmcibParam);
            //订单导入
            if(!flag){
                logger.info("订单导入失败");
                m.addObject("info", "订单导入失败");
                m.setViewName(B2BConstants.WEB_ERROR);
                return m;
            }

            logger.info("订单导入成功");

            logger.info("订单支付请求开始");

            //支付请求
            PayRequestFmcibParam payParam=this.putPayParam(emCUser,order);
            
            System.out.println(JSON.toJSONString(payParam));
            m.addObject("payParam",payParam);

            m.setViewName("/center/trade/pay/fmcib/post_do");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            m.setViewName(B2BConstants.WEB_ERROR);
        }
        return  m;
    }

    private PayRequestFmcibParam putPayParam(EmCUser emCUser,EmSOrder order)throws NullPointerException{
        PayRequestFmcibParam param=new PayRequestFmcibParam();
        StringBuffer signature=new StringBuffer();
        param.setVersion("01");
        signature.append("VERSION"+param.getVersion());

        param.setCustId(this.TK_CUST_ID);
        signature.append("CUSTID"+param.getCustId());

        param.setPayerCode(emCUser.getUserId().toString());
        signature.append("PAYERCODE"+param.getPayerCode());

        param.setPayerName(emCUser.getUserName().trim());
        signature.append("PAYERNAME"+param.getPayerName());

        param.setPayerMobilePhone(emCUser.getMobilePhone()==null?"":emCUser.getMobilePhone());
        signature.append("PAYERMOBILEPHONE"+param.getPayerMobilePhone());

        param.setOrderCode(order.getOrderCode());
        signature.append("ORDERCODE"+param.getOrderCode());

        param.setOrderTitle(this.ORDER_TITLE);
        signature.append("ORDERTITLE"+param.getOrderTitle());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        param.setOrderDate(sdf.format(order.getUpdateDate()));
        signature.append("ORDERDATE"+param.getOrderDate());

        param.setOrderAmount(order.getConfirmMoney());
        NumberFormat nf = new DecimalFormat("#0.00");
        signature.append("ORDERAMOUNT"+nf.format(param.getOrderAmount()));

        param.setReturnURL("http://www.tkyywl.com/");
        signature.append("RETURNURL" + param.getReturnURL());

        param.setCancelURL("");
        signature.append("CANCELURL");

        param.setPaymentOption("");
        signature.append("PAYMENTOPTION");

        param.setCustomField("");
        signature.append("CUSTOMFIELD"+param.getCustomField());

        signature.append(this.TK_KEY);
        String signStr=Md5encode.encodeByMD5(signature.toString());

        param.setSignature(signStr);

        param.setUrl(this.PAY_SELECT_URL);
        return param;
    }

    private OrderInFmcibParam putOrderInParam(EmSOrder order,EmCUser emCUser) throws Exception {

        StringBuffer signature=new StringBuffer();
        OrderInFmcibParam param =new OrderInFmcibParam();
        param.setCustId(this.TK_CUST_ID);
        signature.append("CUSTID"+param.getCustId());

        param.setOrderNo(order.getOrderCode());
        signature.append("ORDERNO"+param.getOrderNo());

        param.setContractNo(order.getOrderCode());
        signature.append("CONTRACTNO"+param.getContractNo());

        param.setReceivableNo(this.TK_RECEIVABLE_NO);
        signature.append("RECEIVABLENO"+param.getReceivableNo());

        param.setBuyerName(emCUser.getUserName().trim());
        signature.append("BUYERNAME"+param.getBuyerName());

        param.setBuyerLevel(1);
        signature.append("BUYERLEVEL"+param.getBuyerLevel());

        NumberFormat nf = new DecimalFormat("#0.00");
        param.setAmount(order.getTotalMoney());
        signature.append("AMOUNT"+nf.format(param.getAmount()));

        param.setReceivableAmount(order.getConfirmMoney());
        signature.append("RECEIVABLEAMOUNT"+nf.format(param.getReceivableAmount()));

        param.setFactory("tkb2b");
        signature.append("FACTORY"+param.getFactory());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        param.setOrderDate(sdf.format(order.getUpdateDate()));
        signature.append("ORDERDATE"+param.getOrderDate());

        Date date=new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, 1);// 24小时制
        date = cal.getTime();
        param.setReceivableDueDate(sdf.format(date));
        signature.append("RECEIVABLEDUEDATE"+param.getReceivableDueDate());

        param.setPayDate(sdf.format(date));
        signature.append("PAYDATE"+param.getPayDate());

        signature.append(this.TK_KEY);
        String signStr=signature.toString();

        logger.info("订单导入MD5加密前数据："+signStr);

        signStr=Md5encode.encodeByMD5(signStr);

        param.setSignature(signStr);
        Goods goods=new Goods();
        goods.setGoodsName("药品");
        goods.setSpec("A001");
        goods.setUnit("箱");
        goods.setQty(1);
        goods.setPrice(1.0);
        param.setGoods("["+JSON.toJSONString(goods)+"]");

        param.setUrl(ORDER_SAVE_URL);

        return param;
    }

    private boolean doPostStatus(OrderInFmcibParam param)throws Exception{

        logger.info("兴业订单导入请求数据："+param.toString());

        HttpClient httpclient = new HttpClient();
        httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");
        PostMethod postmethod = new PostMethod(ORDER_SAVE_URL);
        NumberFormat nf = new DecimalFormat("#0.00");
        NameValuePair[] data = { new NameValuePair("custId", param.getCustId()),
                new NameValuePair("orderNo", param.getOrderNo()), new NameValuePair("contractNo", param.getContractNo()),
                new NameValuePair("receivableNo", param.getReceivableNo()), new NameValuePair("buyerName", param.getBuyerName()),
                new NameValuePair("buyerLevel", param.getBuyerLevel().toString()), new NameValuePair("amount", nf.format(param.getAmount())),
                new NameValuePair("receivableAmount", nf.format(param.getReceivableAmount())),new NameValuePair("factory", param.getFactory()),
                new NameValuePair("orderDate", param.getOrderDate()),new NameValuePair("receivableDueDate", param.getReceivableDueDate()),
                new NameValuePair("payDate", param.getPayDate()),new NameValuePair("signature", param.getSignature()),
                new NameValuePair("goods", param.getGoods())};

        postmethod.setRequestBody(data);
        int responseCode = httpclient.executeMethod(postmethod);
        String status="0";
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String strResponse = postmethod.getResponseBodyAsString();
            // 解析查询返回结果
            strResponse = URLDecoder.decode(strResponse);

            logger.info("兴业返回查询结果：["+strResponse+"]");

            JSONArray res=JSON.parseArray("["+strResponse+"]");
            Map<String,Object> map=(Map<String,Object>)res.get(0);
            status=map.get("status").toString();
            if(status.equals("1")){
                return true;
            }else{
                logger.error(map.get("msg"));
                throw new RuntimeException(map.get("msg").toString());
            }
        } else {
            logger.error("网络不通,无法查询！");
            throw new RuntimeException("网络不通,无法查询！");
        }
    }

    @RequestMapping("recviceFmcib.s")
    public ModelAndView recviceFmcib(PayRequestFmcibParam param,HttpServletRequest req) {
        ModelAndView m=new ModelAndView();
        try {
            if (this.doSign(param)) {
                logger.info("商户订单处理开始");
                // 更新订单状态 和 支付表数据

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                EmSOrder order = new EmSOrder();
                order.setOrderCode(param.getOrderCode());
                order.setStatus(Double.parseDouble("20"));

                Date paymentDate=sdf.parse(param.getPaymentDate());
                sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                order.setFeeDate(sdf.format(paymentDate));

                order.setTranSerialNo(param.getPaymentReference());
                order.setFeeAmount(param.getPaymentAmount());
                order.setOrderType(1);
                emSOrderDao.updateEmSOrder(order);

                sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                EmSPayment payment = new EmSPayment();

                payment.setPaymentFrom("PC");
                payment.setPaymentMedthod("兴业随兴盈");
                payment.setPaymentMoney(param.getPaymentAmount());
                payment.setPaymentCompleteDate(sdf.parse(param.getPaymentDate()));
                payment.setTranSerialNo(param.getPaymentReference());
                payment.setPaymentStatus(1);
                payment.setDealFlag(1);

                emSPaymentService.updateEmSPayment(payment);
                m.setViewName("/center/trade/pay/fmcib/recvice_success");
                m.addObject("info", "商户订单处理完成");
                logger.info("商户订单处理完成");

            } else {
                logger.error("兴业返回数据签名失败");
                m.addObject("error", "兴业返回数据签名失败");
                m.setViewName("/center/trade/pay/fmcib/recvice_fail");
                throw new RuntimeException("兴业返回数据签名失败");
            }
        } catch (ParseException e) {
            logger.error("兴业返回数据签名失败", e);
            m.addObject("error", "兴业返回数据签名失败");
            m.setViewName("/center/trade/pay/fmcib/recvice_fail");
        }
        return m;
    }

    private boolean doSign(PayRequestFmcibParam param){
        logger.info("兴业回调参数："+param.toString());

        StringBuffer signature=new StringBuffer();
        signature.append("VERSION").append(param.getVersion());
        signature.append("CUSTID").append(param.getCustId());
        signature.append("ORDERCODE").append(param.getOrderCode());
        signature.append("PAYMENTMODEID").append(param.getPaymentModeId());
        signature.append("PAYMENTDATE").append(param.getPaymentDate());
        NumberFormat nf = new DecimalFormat("#0.00");
        signature.append("PAYMENTAMOUNT").append(nf.format(param.getPaymentAmount()));
        signature.append("PAYMENTREFERENCE").append(param.getPaymentReference());
        signature.append("PAYMENTREFERENCEALIAS").append(param.getPaymentReferenceAlias());
        signature.append("CUSTOMFIELD").append(param.getCustomField());

        signature.append(this.TK_KEY);

        logger.info("兴业返回数据数据明文：["+signature.toString()+"]");

        String signStr=Md5encode.encodeByMD5(signature.toString());

        logger.info("兴业返回数据进行数据签名：["+signStr+"]");
        logger.info("兴业返回签名：["+param.getSignature()+"]");

        return signStr.equals(param.getSignature());
    }
}
